<template>
    <div class="iotrulesAdd-page">
        <el-form ref="ruleFormRef" :model="from" :rules="rules" label-width="auto" :inline="true">
            <el-form-item prop="deptId">
                <el-select v-model="from.triggerMethod" placeholder="请选择" style="width: 240px">
                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
            </el-form-item>
            <el-form-item prop="rulesName">
                <el-input v-model="from.rulesName" style="width: 240px" placeholder="请输入规则名称" />
            </el-form-item>
            <el-form-item label="选择cron表达式" v-if="from.triggerMethod === 1" style="width: 100%;">
                <Vue3Cron @update:value="handleCronChange" v-model:value="from.cron"></Vue3Cron>
            </el-form-item>
        </el-form>
        <!-- 联动 -->
        <template v-if="from.triggerMethod === 2">
            <el-card>
                <template #header>
                    <h3>设备监听器</h3>
                </template>
                <el-space direction="vertical" style="margin-bottom: 30px;align-items: flex-start;">
                    <el-card h="30" w="30" m="2" :style="{
                        boxShadow: `var(--el-box-shadow-light)`,
                    }">
                        <el-select v-model="linkageControlDTOS.deviceIds" multiple placeholder="请选择设备" style="width: 240px">
                            <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceCode"
                                :value="item.deviceCode">
                            </el-option>
                        </el-select>
                        <el-space wrap style="margin-top: 30px;display: flex;"
                            v-for="(itemFun, indexFun) of linkageControlDTOS.functions">

                            <el-select v-model="itemFun.fun" placeholder="请选择属性" style="width: 240px">
                                <el-option v-for="item in attributeDropdown" :key="item.attributeCode"
                                    :label="item.attributeName" :value="item.attributeCode">
                                </el-option>
                            </el-select>

                            <el-select v-model="itemFun.formula" placeholder="请选择公式" style="width: 240px"
                                v-if="!isShowF(itemFun.fun, 'enum')">
                                <el-option v-for="fItem in formula" :key="fItem.value" :label="fItem.label"
                                    :value="fItem.value">
                                </el-option>
                            </el-select>

                            <!-- 枚举 -->
                            <el-select v-model="itemFun.value" placeholder="请选择类型" style="width: 240px"
                                v-if="isShowF(itemFun.fun, 'enum')">
                                <el-option v-for="itemEnums in isShowF(itemFun.fun, 'enum')" :key="itemEnums.id"
                                    :label="itemEnums.label" :value="itemEnums.id">
                                </el-option>
                            </el-select>
                            <!-- 其他 -->
                            <el-input-number v-model="itemFun.value" style="width: 240px" placeholder="请输入时间表达式"
                                v-else-if="isShowF(itemFun.fun, 'other')" />

                            <el-button type="primary" :icon="Plus" title="新增" @click="attributeDropdownAdd"
                                v-if="indexFun === linkageControlDTOS.functions.length - 1"></el-button>
                        </el-space>

                    </el-card>
                </el-space>
            </el-card>
        </template>
        <!-- 定时 -->
        <el-card>
            <template #header>
                <h3>设备执行动作</h3>
            </template>
            <el-space direction="vertical" style="margin-bottom: 30px;align-items: flex-start;width: 100%;">
                <el-card v-for="(itemVOS, index) of deviceVOS" h="30" w="30" m="2" :style="{
                    boxShadow: `var(--el-box-shadow-light)`,
                    width: '100%'
                }">
                    <div style="display: flex;align-items: flex-start;gap: 30px;">
                        <el-select v-model="itemVOS.deviceIds" multiple placeholder="请选择设备" style="width: 240px">
                            <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceCode"
                                :value="item.deviceCode">
                            </el-option>
                        </el-select>
                        <div style="display: flex;flex-direction: column;gap: 20px;">
                            <el-space v-for="(itemFun, indexFun) of itemVOS.functions">

                                <el-select v-model="itemFun.fun" placeholder="请选择功能" style="width: 240px">
                                    <el-option v-for="item in functionDropdown" :key="item.functionCode"
                                        :label="item.functionName" :value="item.functionCode">
                                    </el-option>
                                </el-select>
                                <!-- 枚举 -->
                                <el-select v-model="itemFun.value" placeholder="请选择类型" style="width: 240px"
                                    v-if="isShow(itemFun.fun, 'enum')">
                                    <el-option v-for="itemEnums in isShow(itemFun.fun, 'enum')" :key="itemEnums.id"
                                        :label="itemEnums.label" :value="itemEnums.id">
                                    </el-option>
                                </el-select>
                                <!-- 其他 -->
                                <el-input-number v-model="itemFun.value" style="width: 240px" placeholder="请输入时间表达式"
                                    v-else-if="isShow(itemFun.fun, 'other')" />

                                <el-button type="primary" :icon="Plus" title="新增" @click="functionsAdd(index)"
                                    v-if="indexFun === itemVOS.functions.length - 1"></el-button>
                            </el-space>
                        </div>
                    </div>
                </el-card>
                <el-button type="primary" :icon="Plus" title="新增" @click="timedAdd">新增</el-button>
            </el-space>
        </el-card>
        <el-space wrap style="margin-top: 30px;display: flex;
        justify-content: flex-end;">
            <el-button @click="clearAdd">取消</el-button>
            <el-button type="primary" @click="submitAdd">确定</el-button>
        </el-space>
    </div>
</template>

<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { getDeviceList, getFunctionDropdown, getIotrulesDetail, getIotrulesAttributeDropdown } from "@/api/desk/iotrules"
import { Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import Vue3Cron from './cron.vue'

const emit = defineEmits(['submitAdd', 'clearAdd'])
const definePropsInfo = defineProps({
    fromItem: {
        type: Object,
        default: () => (null)
    }
})

const options = ref([{
    label: '定时控制',
    value: 1
}, {
    label: '联动控制',
    value: 2
}])
const deviceVOS = ref([{
    deviceIds: [],
    functions: [{
        fun: '',
        value: ''
    }]
}])
const from = ref({
    triggerMethod: 2,
    rulesName: '',
    cron: ''
})
const rules = reactive({
    triggerMethod: [
        {
            required: true,
            message: '请选择出发方式',
            trigger: 'change',
        }],
    rulesName: [
        {
            required: true,
            message: '请输入规则名称',
            trigger: 'change',
        }],
    cron: [
        {
            required: true,
            message: '请输入cron表达式',
            trigger: 'change',
        }],
    deviceVOS: [
        {
            required: true,
            message: '请选择设备',
            trigger: 'change',
        }],
})
const ruleFormRef = ref()
const deviceList = ref([])
const functionDropdown = ref()
const attributeDropdown = ref()
const linkageControlDTOS = ref({
    deviceIds: [],
    functions: [{
        fun: '',
        value: '',
        formula: 1
    }]
})
// 1:大于;2小于;3等于;4不等于;5大于等于;6小于等于
const formula = [{
    value: 1,
    label: '大于'
}, {
    value: 2,
    label: '小于'
}, {
    value: 3,
    label: '等于'
}, {
    value: 4,
    label: '不等于'
}, {
    value: 5,
    label: '大于等于'
}, {
    value: 6,
    label: '小于等于'
}]

const handleCronChange = (val: string) => {
    if (typeof val !== "string") return false;
    console.log('你定义的cron值 = val', val)
};

// 定时添加
const timedAdd = () => {
    deviceVOS.value.push({
        deviceIds: [],
        functions: [{
            fun: '',
            value: ''
        }]
    })
}
const functionsAdd = (index) => {
    deviceVOS.value[index]['functions'].push({
        fun: '',
        value: ''
    })
}
const attributeDropdownAdd = () => {
    linkageControlDTOS.value['functions'].push({
        fun: '',
        value: '',
        formula: 1
    })
}

const getEnum = (str) => {
    return str.split(';').map(item => {
        const [label, id] = item.split(':');
        return {
            id: id?.trim(),
            label: label?.trim()
        };
    }).filter(item => item.id && item.label);
};
// 是否显示
const isShowF = (code, type) => {
    if (!code) {
        return false
    }
    const items = attributeDropdown.value.filter(item => item.attributeCode === code)[0]
    if (type === 'enum') {
        return items.enums
    }
    if (type === 'other') {
        return items.fieldType && items.fieldType !== 'enum'
    }
    return items.fieldType === type
}
const isShow = (code, type) => {
    if (!code) {
        return false
    }
    const items = functionDropdown.value.filter(item => item.functionCode === code)[0]
    if (type === 'enum') {
        return items.enums
    }
    if (type === 'other') {
        return items.fieldType && items.fieldType !== 'enum'
    }
    return items.fieldType === type
}

// 取消
const clearAdd = () => {
    emit('clearAdd')
}

interface DeviceInfo {
    deviceId: string;
    deviceCode: string;
    controlParametersVOS: ControlParameter[];
}

interface ControlParameter {
    functionName: string;
    functionCode: string;
    value: unknown;  // 更安全的 any 替代方案
}

interface FunctionItem {
    fun?: string;
    value: unknown;
}

interface DeviceVO {
    deviceIds: string[];
    functions: FunctionItem[];
}

const getDeviceVOS = (): DeviceInfo[] | false => {
    // 提前终止条件 - 更清晰的空值检查
    if (deviceVOS.value.length === 0) {
        return false;
    }

    // 使用显式类型注解避免隐式 any
    return deviceVOS.value.reduce<DeviceInfo[] | false>((acc, d: DeviceVO) => {
        // 失败状态传播检查
        if (acc === false || d.deviceIds.length === 0 || d.functions.length === 0) {
            return false;
        }

        // 处理设备ID - 使用显式类型
        return d.deviceIds.reduce<DeviceInfo[] | false>((deviceAcc: any, deviceCode) => {
            if (deviceAcc === false) return false;

            // 使用可选链和空值合并
            const deviceItem = deviceList.value.find(i => i.deviceCode === deviceCode);
            if (!deviceItem) return false;

            const deviceId = deviceItem.id;
            const currentDevice = {
                deviceId,
                deviceCode,
                controlParametersVOS: []
            };
            deviceAcc.push(currentDevice);

            // 功能验证 - 提取为独立函数更清晰
            const areAllFunctionsValid = validateAndAddFunctions(d.functions, currentDevice);
            return areAllFunctionsValid ? deviceAcc : false;
        }, acc);
    }, [] as DeviceInfo[]); // 显式初始化空数组
};

// 提取功能验证逻辑为独立函数
function validateAndAddFunctions(
    functions: FunctionItem[],
    targetDevice: DeviceInfo
): boolean {
    return functions.every(f => {
        if (!f.fun) return false;

        const funInfo = functionDropdown.value.find(i => i.functionCode === f.fun);
        if (!funInfo) return false;

        // 更严格的必填字段检查
        if (funInfo.fieldType && (f.value === undefined || f.value === null)) {
            return false;
        }

        targetDevice.controlParametersVOS.push({
            functionName: funInfo.functionName,
            functionCode: f.fun,
            value: Number(f.value)
        });

        return true;
    });
}

const getLinkageControlDTOS = () => {
    if (linkageControlDTOS.value.deviceIds.length === 0) {
        return false;
    }
    return linkageControlDTOS.value.deviceIds.map((acc: any) => {
        const deviceCode = acc
        const deviceInfos = deviceList.value.find(d => d.deviceCode === deviceCode)
        const deviceId = deviceInfos.id
        const linkageConditionDTOS = linkageControlDTOS.value.functions.map(f => {
            const linInfo = attributeDropdown.value.find(a => a.attributeCode === f.fun)
            return {
                functionName: linInfo.attributeName,
                functionCode: linInfo.attributeCode,
                formula: f.formula,
                value: f.value
            }
        })
        return {
            deviceId,
            deviceCode,
            linkageConditionDTOS
        }
    })
}


// 确定
const submitAdd = () => {
    if (!ruleFormRef.value) return
    let lDTOS = []
    if (from.value.triggerMethod === 2) {
        lDTOS = getLinkageControlDTOS()
        if (!lDTOS) {
            ElMessage({
                type: 'warning',
                message: '请完善信息输入',
            })
            return
        }
    }
    if (from.value.triggerMethod === 1 && !from.value.cron) {
        if (!lDTOS) {
            ElMessage({
                type: 'warning',
                message: '请完善信息输入',
            })
            return
        }
    }

    const dVOS = getDeviceVOS()
    if (!from.value.rulesName || !dVOS) {
        ElMessage({
            type: 'warning',
            message: '请完善信息输入',
        })
        return
    }

    ruleFormRef.value.validate((valid, fields) => {
        if (valid) {
            emit('submitAdd', {
                ...from.value,
                deviceVOS: dVOS,
                linkageControlDTOS: lDTOS
            })
        } else {
            console.log('error submit!', fields)
        }
    })
}

// 获取设备列表
const getDevices = () => {
    getDeviceList({
        current: 1,
        size: 1000
    }).then((res) => {
        deviceList.value = res.data.data.records
    })
}

// 获取功能列表
const getFunctionDropdowns = () => {
    getFunctionDropdown().then((res) => {
        functionDropdown.value = res.data.data.map((item) => {
            if (item.fieldType === 'enum') {
                item.enums = getEnum(item.specEnum)
            }
            return item
        })
    })
}
// 获取属性列表
const getIotrulesAttributeDropdowns = () => {
    getIotrulesAttributeDropdown().then((res) => {
        attributeDropdown.value = res.data.data.map((item) => {
            if (item.fieldType === 'enum') {
                item.enums = getEnum(item.specEnum)
            }
            return item
        })
    })
}
// 格式化定时数据
const initData1 = (data: any) => {
    const result: any = []
    data.map((item) => {
        const cpv = item.controlParametersVOS.map(c => {
            return {
                fun: c.functionCode,
                value: c.value
            }
        })
        const infos = result.find(r => r.functions && JSON.stringify(r.functions) === JSON.stringify(cpv))
        if (!infos) {
            result.push({
                deviceIds: [item.deviceCode],
                functions: cpv
            })
        } else {
            result.map(r => {
                if (r.functions && JSON.stringify(r.functions) === JSON.stringify(cpv)) {
                    r.deviceIds.push(item.deviceCode)
                }
            })
        }
    })
    deviceVOS.value = result
}

const initData2 = (data: any) => {
    data.map((d) => {
        linkageControlDTOS.value.deviceIds.push(d.deviceCode)
    })
    linkageControlDTOS.value.functions = data[0]['linkageConditionDTOS'].map((l) => {
        return {
            fun: l.functionCode,
            value: l.value,
            formula: l.formula
        }
    })
}

// 获取详情
const getIotrulesDetailInfo = () => {
    getIotrulesDetail(definePropsInfo.fromItem.id).then((res) => {
        from.value = res.data.data
        initData1(res.data.data.deviceVOS)
        if (res.data.data.triggerMethod === 2) {
            initData2(res.data.data.linkageControlVOS)
        }
    })
}

getDevices()
getFunctionDropdowns()
getIotrulesAttributeDropdowns()
onMounted(() => {
    if (definePropsInfo.fromItem?.id) {
        getIotrulesDetailInfo()
    }
})

</script>
